/**
 *  jQuery.jsonengine
 */
(function($) {
	$.jsonengine = function() {	};
	$.jsonengine.version = '03-04-2011';
})(jQuery);

/**
 *  jQuery.jsonengine.utils
 */
(function($) {
	$.jsonengine.utils = function() {
	};
	$.jsonengine.utils.escapetag = function(string) {
		if (Object.prototype.toString.call(string) !== '[object String]') return string;
		return string.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
	};
	/**
	 * jsonデータをhtmlリスト形式へ
	 */
	$.jsonengine.utils.json2html = function(json) {
		if (!json) {
			return json;
		} else if (Object.prototype.toString.call(json) === '[object Object]') {
			var dl = $('<dl class="object_Object">');
			for ( var key in json) {
				//将来的に<span class="object">は埋め込まない。html2jsonに任せる。
				dl.append($('<span class="object">')
					.append($('<dt class="key">').html( this.escapetag(key) ))
					.append($('<dd class="value">').html( this.escapetag( this.json2html(json[key]) ))));
			}
			return dl;
		} else if (Object.prototype.toString.call(json) === '[object Array]') {
			var ol = $('<ol class="object_Array">');
			var json_length = json.length;
			for ( var i = 0; i < json_length; i++) {
				ol.append($('<li class="value">').html( this.escapetag( this.json2html(json[i]) )));
			}
			return ol;
		} else {
			return json;
		}
	};
	/**
	 * htmlリストをjsonデータ形式へ
	 */
	$.jsonengine.utils.html2json = function(html) {
		//TODO dt,dd ペアを<span class="object">で囲む処理を書く。
		html2json_exec = function(src) {
			if (!src) return src;
			src = $(src);
			object_Object = src.attr('class').match(/object_Object/);
			object_Array = src.attr('class').match(/object_Array/);
			if (object_Object) {
				var object = {};
				var children = src.children();
				for (var i = 0; i < children.length; i++) {
					var o = children.eq(i);
					//ネストしていない？
					if (!o.children().filter('.value').find('dl,ol').length) {
						object[o.children().filter('.key').eq(0).text()] = 
							o.children().filter('.value').eq(0).text();
					} else {
						object[o.children().filter('.key').eq(0).text()] = 
							html2json_exec(o.children().filter('.value').eq(0).children()[0]);
					}
				}
				return object;
			} else if (object_Array) {
				var array = [];
				var children = src.children();
				for (var i = 0; i < children.length; i++) {
					var grandChildren = children.eq(i).children();
					if (grandChildren.length == 0) {
						array[i] = children.eq(i).text();
					} else {
						array[i] = html2json_exec(grandChildren);
					}
				}
				return array;
			} else {
				return src;
			}
		}
		return html2json_exec(html);
	};
})(jQuery);

/**
 *  jQuery.fn.jsonengine
 */
(function($) {
	$.jsonengine.fn = function() { };
	/**
	 * htmlに記述された情報からdocType文字列を構築する
	 */
	$.jsonengine.fn.docType = function(o) {
		try {
			return o
				.attr('class')
				.match(/_je_.*?\b/)[0]
				.replace('_je_','');
		} catch(e) {
			return;
		}
	};
	/**
	 * htmlに記述された情報からURL文字列を構築する
	 */
	$.jsonengine.fn.url = function(o) {
		d = this.docType(o);
		if(!d) return;
		return '/_je/' + d + o
			.find('span.query').eq(0)
			.text()
			.trim();
	};
	/**
	 * $.ajax(option)のラッパー
	 */
	$.jsonengine.fn.ajax = function(o) {
		$.ajax(o);
	};
	/**
	 * $.ajaxコールバック関数へ引数を渡すための関数 成功用
	 */
	$.jsonengine.fn.success = function(o, f) {
		return function(response, status) {
			f(o, response, status);
		};
	};
	/**
	 * コールバック関数へ引数を渡すための関数 失敗用
	 */
	$.jsonengine.fn.error = function(o, f) {
		return function(xhr, status, thrown) {
			f(o, xhr, status, thrown);
		};
	};
	/**
	 * jsonengineからデータ読み込み成功した際のコールバック関数
	 */
	$.jsonengine.fn.success_LOAD = function(o, response, status) {
		tmp = o.find('span.query');
		o.empty();
		o.append(tmp);
		// htmlリストを追加
		e = $.jsonengine.utils.json2html(response);
		if(e.html()!==''){
			e.addClass('result');
			o.append(e);
		}
	};
	/**
	 * jsonengineからデータ読み込み失敗した際のコールバック関数
	 */
	$.jsonengine.fn.error_LOAD = function(o, xhr, status, thrown){
		o.append($('<div class="error">')
			.append('status:')
				.append($('<span style="color:red;font-weight:bold;">')
					.append(status)));
	};
	/**
	 * プラグインのベース関数
	 */
	$.jsonengine.fn.base = function(o){
		u = this.url(o.object);
		if (!u) return;
		if (o.users_success) o.success = o.users_success;
		if (o.users_error) o.error = o.users_error;
		$.jsonengine.fn.ajax({
			"type"    : o.type,
			"url"     : u,
			"data"    : o.data,
			"success" : this.success(o.object, o.success),
			"error"   : this.error(o.object, o.error)
		});
	};
	// プラグインの定義
	$.fn.extend( {
		/**
		 * jsonengineから取得したjsonをhtmlリストへ変換し表示用要素内に追加するプラグイン
		 */
		_LOAD : function(s, e) {
			for(i=0; i < this.length; i++){
				$.jsonengine.fn.base({
					"type"    : "GET",
					"data"    : "",
					"success" : $.jsonengine.fn.success_LOAD,
					"error"   : $.jsonengine.fn.error_LOAD,
					"object"        : this.eq(i),
					"users_success" : s,
					"users_error"   : e
				});
			}
			return this;
		},
		/**
		 * フォームに入力されたデータをjsonengineへ登録し、表示エリアを再読込するプラグイン
		 */
		_POST : function(s, e) {
			form = $(this.get(0).form);
			console.log(this.eq(0).form)
			return form;
		}
	});
})(jQuery);
